import struct
from codecs import StreamReader
import os
from . import Importer

def read_float32(f):
    return round(struct.unpack('f', f.read(4))[0], 4)


def read_float16(f):
    return round(struct.unpack('f', f.read(2))[0], 4)


def read_int32(f):
    return int.from_bytes(f.read(4), 'little')


def read_int16(f):
    return int.from_bytes(f.read(2), 'little')

class PartObj():
    def __init__(self):
        super().__init__()
        self.name = ''
        self.vertices = []
        self.uvs = []
        self.indices = []
        self.uvindices = []
        self.normals = []
        self.normalindice = []
        self.child = []
        self.coord = []
        self.scale = []

        self.bbmax = []
        self.bbmin = []

def read_dummy(f):
    Obj = PartObj()
    id = read_int16(f)
    namecount = read_int32(f)
    name = f.read(namecount*2).replace(b'\x00', b'').decode('utf-8')
    Obj.name = name
    NumberOfChild = read_int32(f)
    for i in range(NumberOfChild):
        flag = f.read(6)
        if flag == b'\xAA\x47\x46\x04\x2A\x19':
            if NumberOfChild == 1:
                Obj = read_mesh(f, False)
                Obj.name = name
            else:
                Obj.child.append(read_mesh(f, False))
        elif flag == b'\xAA\x47\x3C\x03\x07\x0E':
            Obj.child.append(read_dummy(f))
    print(name)
    f.read(0x20)
    f.read(4)
    print(f.tell())
    z = read_float32(f)
    y = read_float32(f)*-1
    x = 0
    f.read(4)
    Obj.coord = [x,y,z]
    x = read_float32(f)
    y = read_float32(f)
    z = read_float32(f)
    Obj.scale = [x,y,z]
    x = read_float32(f)
    y = read_float32(f)
    z = read_float32(f)
    Obj.bbmin = [x,y,z]
    x = read_float32(f)
    y = read_float32(f)
    z = read_float32(f)
    Obj.bbmax = [x,y,z]
    f.read(0x2E)
    return Obj

def read_mesh(f, isbody):
    Obj = PartObj()
    id = read_int16(f)
    namecount = read_int32(f)
    name = f.read(namecount*2).replace(b'\x00', b'').decode('utf-8')
    f.read(4)
    scale_x = read_float32(f)
    f.read(0xC)
    scale_y = read_float32(f)
    x = read_float32(f)
    y = read_float32(f)*-1
    z = read_float32(f)
    Obj.rotation = [x,y,z]
    scale_z = read_float32(f)
    Obj.scale = [scale_x,scale_y,scale_z]
    x = read_float32(f)
    y = read_float32(f)
    z = read_float32(f)
    Obj.coord = [x,y,z]
    x = read_float32(f)
    y = read_float32(f)
    z = read_float32(f)
    Obj.scale_before = [x,y,z]
    x = read_float32(f)
    y = read_float32(f)
    z = read_float32(f)
    Obj.bbmin = [x,y,z]
    x = read_float32(f)
    y = read_float32(f)
    z = read_float32(f)
    Obj.bbmax = [x,y,z]
    f.read(0x32)
    if f.read(2) == b'\xAA\x27':
        f.read(2)

        vertices = []
        uvs = []
        Indices = []
        uvindices = []


        if isbody == True:
            VertexCount = read_int32(f)
            VertexOffset = f.tell()
            f.seek(VertexOffset)
            for i in range(0, VertexCount, 1):
                x = read_float32(f)
                y = read_float32(f)
                z = read_float32(f)
                vertices.append([x, y, z])
                f.read(24)

            #normals
            f.seek(VertexOffset+12)
            for i in range(0, VertexCount, 1):
                x = read_float32(f)
                y = read_float32(f)
                z = read_float32(f)
                f.read(24)

            f.seek(-12, 1)
        else:
            verticescount = read_int32(f)
            for i in range(0, verticescount, 1):
                x = read_float32(f)
                y = read_float32(f)
                z = read_float32(f)
                vertices.append([x, y, z])

            normalcount = read_int32(f)
            for i in range(0, normalcount, 1):
                x = read_float32(f)
                y = read_float32(f)
                z = read_float32(f)

        uvcount = read_int32(f)
        f.read(4)
        for i in range(0, uvcount, 1):
            x = read_float32(f)
            y = 1-read_float32(f)
            uvs.append([x, y])
            f.read(4)

        f.seek(-4, 1)

        StructsLength = read_int32(f)
        StructsOffset = f.tell()

        f.seek(StructsOffset)
        for i in range(0, StructsLength, 1):
            one = read_int16(f)
            two = read_int16(f)
            three = read_int16(f)
            uvindices.append([one, two, three])
            f.read(14)

        f.seek(StructsOffset+12)
        for i in range(0, StructsLength, 1):
            one = read_int16(f)+1
            two = read_int16(f)+1
            three = read_int16(f)+1
            Indices.append([one, two, three])
            f.read(14)

        f.seek(-12, 1)

        Obj.name = name
        Obj.vertices = vertices
        Obj.uvs = uvs
        Obj.indices = Indices
        Obj.uvindices = uvindices
    return Obj



def read_character(filepath):
    f = open(filepath, 'rb')
    f.seek(0xC)
    NumOfObjs = read_int32(f)
    Objs = []
    for i in range(NumOfObjs):
        print(f.tell())
        flag = f.read(6)
        if flag == b'\xAA\x47\x46\x04\x2A\x19':
            Objs.append(read_mesh(f, False))
        elif flag == b'\xAA\x47\x3C\x03\x07\x0E':
            Objs.append(read_dummy(f))
        elif flag == b'\xAA\x47\x23\x05\x33\x23':
            Objs.append(read_mesh(f, True))
            count = read_int32(f)
            for i in range(count):
                f.read(0x64)
            f.read(1)
                
    for obj in Objs:
        Importer.write_obj(obj, False)